home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / gdb.new / gdb-4.0 / gdb / expprint.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-24  |  10.7 KB  |  346 lines

  1. /* Print in infix form a struct expression.
  2.    Copyright (C) 1986, 1989 Free Software Foundation, Inc.
  3.  
  4. This file is part of GDB.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <stdio.h>
  21. #include "defs.h"
  22. #include "symtab.h"
  23. #include "param.h"
  24. #include "expression.h"
  25. #include "value.h"
  26.  
  27.  
  28. /* These codes indicate operator precedences, least tightly binding first.  */
  29. /* Adding 1 to a precedence value is done for binary operators,
  30.    on the operand which is more tightly bound, so that operators
  31.    of equal precedence within that operand will get parentheses.  */
  32. /* PREC_HYPER and PREC_ABOVE_COMMA are not the precedence of any operator;
  33.    they are used as the "surrounding precedence" to force
  34.    various kinds of things to be parenthesized.  */
  35. enum precedence
  36. { PREC_NULL, PREC_COMMA, PREC_ABOVE_COMMA, PREC_ASSIGN, PREC_OR, PREC_AND,
  37.   PREC_LOGIOR, PREC_LOGAND, PREC_LOGXOR, PREC_EQUAL, PREC_ORDER,
  38.   PREC_SHIFT, PREC_ADD, PREC_MUL, PREC_REPEAT,
  39.   PREC_HYPER, PREC_PREFIX, PREC_SUFFIX };
  40.  
  41. /* Table mapping opcodes into strings for printing operators
  42.    and precedences of the operators.  */
  43.  
  44. struct op_print
  45. {
  46.   char *string;
  47.   enum exp_opcode opcode;
  48.   /* Precedence of operator.  These values are used only by comparisons.  */
  49.   enum precedence precedence;
  50.   int right_assoc;
  51. };
  52.  
  53. const static struct op_print op_print_tab[] =
  54.   {
  55.     {",", BINOP_COMMA, PREC_COMMA, 0},
  56.     {"=", BINOP_ASSIGN, PREC_ASSIGN, 1},
  57.     {"||", BINOP_OR, PREC_OR, 0},
  58.     {"&&", BINOP_AND, PREC_AND, 0},
  59.     {"|", BINOP_LOGIOR, PREC_LOGIOR, 0},
  60.     {"&", BINOP_LOGAND, PREC_LOGAND, 0},
  61.     {"^", BINOP_LOGXOR, PREC_LOGXOR, 0},
  62.     {"==", BINOP_EQUAL, PREC_EQUAL, 0},
  63.     {"!=", BINOP_NOTEQUAL, PREC_EQUAL, 0},
  64.     {"<=", BINOP_LEQ, PREC_ORDER, 0},
  65.     {">=", BINOP_GEQ, PREC_ORDER, 0},
  66.     {">", BINOP_GTR, PREC_ORDER, 0},
  67.     {"<", BINOP_LESS, PREC_ORDER, 0},
  68.     {">>", BINOP_RSH, PREC_SHIFT, 0},
  69.     {"<<", BINOP_LSH, PREC_SHIFT, 0},
  70.     {"+", BINOP_ADD, PREC_ADD, 0},
  71.     {"-", BINOP_SUB, PREC_ADD, 0},
  72.     {"*", BINOP_MUL, PREC_MUL, 0},
  73.     {"/", BINOP_DIV, PREC_MUL, 0},
  74.     {"%", BINOP_REM, PREC_MUL, 0},
  75.     {"@", BINOP_REPEAT, PREC_REPEAT, 0},
  76.     {"-", UNOP_NEG, PREC_PREFIX, 0},
  77.     {"!", UNOP_ZEROP, PREC_PREFIX, 0},
  78.     {"~", UNOP_LOGNOT, PREC_PREFIX, 0},
  79.     {"*", UNOP_IND, PREC_PREFIX, 0},
  80.     {"&", UNOP_ADDR, PREC_PREFIX, 0},
  81.     {"sizeof ", UNOP_SIZEOF, PREC_PREFIX, 0},
  82.     {"++", UNOP_PREINCREMENT, PREC_PREFIX, 0},
  83.     {"--", UNOP_PREDECREMENT, PREC_PREFIX, 0},
  84.     /* C++  */
  85.     {"::", BINOP_SCOPE, PREC_PREFIX, 0},
  86.   };
  87.  
  88. static void print_subexp ();
  89.  
  90. void
  91. print_expression (exp, stream)
  92.      struct expression *exp;
  93.      FILE *stream;
  94. {
  95.   int pc = 0;
  96.   print_subexp (exp, &pc, stream, PREC_NULL);
  97. }
  98.  
  99. /* Print the subexpression of EXP that starts in position POS, on STREAM.
  100.    PREC is the precedence of the surrounding operator;
  101.    if the precedence of the main operator of this subexpression is less,
  102.    parentheses are needed here.  */
  103.  
  104. static void
  105. print_subexp (exp, pos, stream, prec)
  106.      register struct expression *exp;
  107.      register int *pos;
  108.      FILE *stream;
  109.      enum precedence prec;
  110. {
  111.   register unsigned tem;
  112.   register int pc;
  113.   unsigned nargs;
  114.   register char *op_str;
  115.   int assign_modify = 0;
  116.   enum exp_opcode opcode;
  117.   enum precedence myprec;
  118.   /* Set to 1 for a right-associative operator.  */
  119.   int assoc;
  120.   value val;
  121.  
  122.   pc = (*pos)++;
  123.   opcode = exp->elts[pc].opcode;
  124.   switch (opcode)
  125.     {
  126.     case OP_SCOPE:
  127.       myprec = PREC_PREFIX;
  128.       assoc = 0;
  129.       (*pos) += 2;
  130.       print_subexp (exp, pos, stream,
  131.             (enum precedence) ((int) myprec + assoc));
  132.       fputs_filtered (" :: ", stream);
  133.       nargs = strlen (&exp->elts[pc + 2].string);
  134.       (*pos) += 1 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
  135.  
  136.       fputs_filtered (&exp->elts[pc + 2].string, stream);
  137.       return;
  138.  
  139.     case OP_LONG:
  140.       (*pos) += 3;
  141.       value_print (value_from_long (exp->elts[pc + 1].type,
  142.                     exp->elts[pc + 2].longconst),
  143.            stream, 0, Val_no_prettyprint);
  144.       return;
  145.  
  146.     case OP_DOUBLE:
  147.       (*pos) += 3;
  148.       value_print (value_from_double (exp->elts[pc + 1].type,
  149.                       exp->elts[pc + 2].doubleconst),
  150.            stream, 0, Val_no_prettyprint);
  151.       return;
  152.  
  153.     case OP_VAR_VALUE:
  154.       (*pos) += 2;
  155.       fputs_filtered (SYMBOL_NAME (exp->elts[pc + 1].symbol), stream);
  156.       return;
  157.  
  158.     case OP_LAST:
  159.       (*pos) += 2;
  160.       fprintf_filtered (stream, "$%d",
  161.             longest_to_int (exp->elts[pc + 1].longconst));
  162.       return;
  163.  
  164.     case OP_REGISTER:
  165.       (*pos) += 2;
  166.       fprintf_filtered (stream, "$%s",
  167.            longest_to_int (reg_names[exp->elts[pc + 1].longconst]));
  168.       return;
  169.  
  170.     case OP_INTERNALVAR:
  171.       (*pos) += 2;
  172.       fprintf_filtered (stream, "$%s",
  173.            internalvar_name (exp->elts[pc + 1].internalvar));
  174.       return;
  175.  
  176.     case OP_FUNCALL:
  177.       (*pos) += 2;
  178.       nargs = longest_to_int (exp->elts[pc + 1].longconst);
  179.       print_subexp (exp, pos, stream, PREC_SUFFIX);
  180.       fputs_filtered (" (", stream);
  181.       for (tem = 0; tem < nargs; tem++)
  182.     {
  183.       if (tem != 0)
  184.         fputs_filtered (", ", stream);
  185.       print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
  186.     }
  187.       fputs_filtered (")", stream);
  188.       return;
  189.  
  190.     case OP_STRING:
  191.       nargs = strlen (&exp->elts[pc + 1].string);
  192.       (*pos) += 2 + (nargs + sizeof (union exp_element)) / sizeof (union exp_element);
  193.       fputs_filtered ("\"", stream);
  194.       for (tem = 0; tem < nargs; tem++)
  195.     printchar ((&exp->elts[pc + 1].string)[tem], stream, '"');
  196.       fputs_filtered ("\"", stream);
  197.       return;
  198.  
  199.     case TERNOP_COND:
  200.       if ((int) prec > (int) PREC_COMMA)
  201.     fputs_filtered ("(", stream);
  202.       /* Print the subexpressions, forcing parentheses
  203.      around any binary operations within them.
  204.      This is more parentheses than are strictly necessary,
  205.      but it looks clearer.  */
  206.       print_subexp (exp, pos, stream, PREC_HYPER);
  207.       fputs_filtered (" ? ", stream);
  208.       print_subexp (exp, pos, stream, PREC_HYPER);
  209.       fputs_filtered (" : ", stream);
  210.       print_subexp (exp, pos, stream, PREC_HYPER);
  211.       if ((int) prec > (int) PREC_COMMA)
  212.     fputs_filtered (")", stream);
  213.       return;
  214.  
  215.     case STRUCTOP_STRUCT:
  216.       tem = strlen (&exp->elts[pc + 1].string);
  217.       (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
  218.       print_subexp (exp, pos, stream, PREC_SUFFIX);
  219.       fputs_filtered (".", stream);
  220.       fputs_filtered (&exp->elts[pc + 1].string, stream);
  221.       return;
  222.  
  223.     case STRUCTOP_PTR:
  224.       tem = strlen (&exp->elts[pc + 1].string);
  225.       (*pos) += 2 + (tem + sizeof (union exp_element)) / sizeof (union exp_element);
  226.       print_subexp (exp, pos, stream, PREC_SUFFIX);
  227.       fputs_filtered ("->", stream);
  228.       fputs_filtered (&exp->elts[pc + 1].string, stream);
  229.       return;
  230.  
  231.     case BINOP_SUBSCRIPT:
  232.       print_subexp (exp, pos, stream, PREC_SUFFIX);
  233.       fputs_filtered ("[", stream);
  234.       print_subexp (exp, pos, stream, PREC_ABOVE_COMMA);
  235.       fputs_filtered ("]", stream);
  236.       return;
  237.  
  238.     case UNOP_POSTINCREMENT:
  239.       print_subexp (exp, pos, stream, PREC_SUFFIX);
  240.       fputs_filtered ("++", stream);
  241.       return;
  242.  
  243.     case UNOP_POSTDECREMENT:
  244.       print_subexp (exp, pos, stream, PREC_SUFFIX);
  245.       fputs_filtered ("--", stream);
  246.       return;
  247.  
  248.     case UNOP_CAST:
  249.       (*pos) += 2;
  250.       if ((int) prec > (int) PREC_PREFIX)
  251.         fputs_filtered ("(", stream);
  252.       fputs_filtered ("(", stream);
  253.       type_print (exp->elts[pc + 1].type, "", stream, 0);
  254.       fputs_filtered (") ", stream);
  255.       print_subexp (exp, pos, stream, PREC_PREFIX);
  256.       if ((int) prec > (int) PREC_PREFIX)
  257.         fputs_filtered (")", stream);
  258.       return;
  259.  
  260.     case UNOP_MEMVAL:
  261.       (*pos) += 2;
  262.       if ((int) prec > (int) PREC_PREFIX)
  263.         fputs_filtered ("(", stream);
  264.       if (exp->elts[pc + 1].type->code == TYPE_CODE_FUNC &&
  265.       exp->elts[pc + 3].opcode == OP_LONG) {
  266.     /* We have a misc function vector fn, probably.  It's encoded
  267.        as a UNOP_MEMVAL (function-type) of an OP_LONG (int, address).
  268.        Swallow the OP_LONG (including both its opcodes); ignore
  269.        its type; print the value in the type of the MEMVAL.  */
  270.     (*pos) += 4;
  271.     val = value_at_lazy (exp->elts[pc + 1].type,
  272.                  exp->elts[pc + 5].longconst);
  273.     value_print (val, stream, 0, Val_no_prettyprint);
  274.       } else {
  275.     fputs_filtered ("{", stream);
  276.     type_print (exp->elts[pc + 1].type, "", stream, 0);
  277.     fputs_filtered ("} ", stream);
  278.         print_subexp (exp, pos, stream, PREC_PREFIX);
  279.       }
  280.       if ((int) prec > (int) PREC_PREFIX)
  281.         fputs_filtered (")", stream);
  282.       return;
  283.  
  284.     case BINOP_ASSIGN_MODIFY:
  285.       opcode = exp->elts[pc + 1].opcode;
  286.       (*pos) += 2;
  287.       myprec = PREC_ASSIGN;
  288.       assoc = 1;
  289.       assign_modify = 1;
  290.       for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
  291.     if (op_print_tab[tem].opcode == opcode)
  292.       {
  293.         op_str = op_print_tab[tem].string;
  294.         break;
  295.       }
  296.       break;
  297.  
  298.     case OP_THIS:
  299.       ++(*pos);
  300.       fputs_filtered ("this", stream);
  301.       return;
  302.  
  303.     default:
  304.       for (tem = 0; tem < sizeof op_print_tab / sizeof op_print_tab[0]; tem++)
  305.     if (op_print_tab[tem].opcode == opcode)
  306.       {
  307.         op_str = op_print_tab[tem].string;
  308.         myprec = op_print_tab[tem].precedence;
  309.         assoc = op_print_tab[tem].right_assoc;
  310.         break;
  311.       }
  312.     }
  313.  
  314.   if ((int) myprec < (int) prec)
  315.     fputs_filtered ("(", stream);
  316.   if ((int) opcode > (int) BINOP_END)
  317.     {
  318.       /* Unary prefix operator.  */
  319.       fputs_filtered (op_str, stream);
  320.       print_subexp (exp, pos, stream, PREC_PREFIX);
  321.     }
  322.   else
  323.     {
  324.       /* Binary operator.  */
  325.       /* Print left operand.
  326.      If operator is right-associative,
  327.      increment precedence for this operand.  */
  328.       print_subexp (exp, pos, stream,
  329.             (enum precedence) ((int) myprec + assoc));
  330.       /* Print the operator itself.  */
  331.       if (assign_modify)
  332.     fprintf_filtered (stream, " %s= ", op_str);
  333.       else if (op_str[0] == ',')
  334.     fprintf_filtered (stream, "%s ", op_str);
  335.       else
  336.     fprintf_filtered (stream, " %s ", op_str);
  337.       /* Print right operand.
  338.      If operator is left-associative,
  339.      increment precedence for this operand.  */
  340.       print_subexp (exp, pos, stream,
  341.             (enum precedence) ((int) myprec + !assoc));
  342.     }
  343.   if ((int) myprec < (int) prec)
  344.     fputs_filtered (")", stream);
  345. }
  346.